using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;
using System.Linq.Expressions;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Repositories
{
    /// <summary>
    /// 分类仓储实现
    /// 提供分类管理的完整数据访问功能，包括层级结构管理和树形操作
    /// </summary>
    public class CategoryRepository : SimpleRepository<Category>, ICategoryRepository
    {
        public CategoryRepository(LowCodeDbContext context) : base(context)
        {
        }

        /// <summary>
        /// 添加分类
        /// </summary>
        public async Task<Category> AddAsync(Category entity)
        {
            entity.CreatedAt = DateTime.UtcNow;
            entity.UpdatedAt = DateTime.UtcNow;
            await _context.Categories.AddAsync(entity);
            await _context.SaveChangesAsync();
            return entity;
        }

        /// <summary>
        /// 获取分类总数
        /// </summary>
        public async Task<int> CountAsync()
        {
            return await _context.Categories.CountAsync();
        }

        /// <summary>
        /// 根据条件获取分类总数
        /// </summary>
        public async Task<int> CountAsync(Expression<Func<Category, bool>> predicate)
        {
            return await _context.Categories.CountAsync(predicate);
        }

        /// <summary>
        /// 删除分类实体
        /// </summary>
        public async Task DeleteAsync(Category entity)
        {
            _context.Categories.Remove(entity);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 根据ID删除分类
        /// </summary>
        public async Task DeleteAsync(object id)
        {
            var entity = await _context.Categories.FindAsync(id);
            if (entity != null)
            {
                _context.Categories.Remove(entity);
                await _context.SaveChangesAsync();
            }
        }

        /// <summary>
        /// 检查分类名称是否存在
        /// </summary>
        public async Task<bool> ExistsAsync(string name, string type, long? parentId = null, long? excludeId = null)
        {
            var query = _context.Categories.AsQueryable();
            
            query = query.Where(c => c.Name == name && c.Type == type);
            
            if (parentId.HasValue)
                query = query.Where(c => c.ParentId == parentId.Value);
            else
                query = query.Where(c => c.ParentId == null);
                
            if (excludeId.HasValue)
                query = query.Where(c => c.Id != excludeId.Value);
                
            return await query.AnyAsync();
        }

        /// <summary>
        /// 检查是否存在满足条件的分类
        /// </summary>
        public async Task<bool> ExistsAsync(Expression<Func<Category, bool>> predicate)
        {
            return await _context.Categories.AnyAsync(predicate);
        }

        /// <summary>
        /// 根据条件查找分类列表
        /// </summary>
        public async Task<List<Category>> FindAsync(Expression<Func<Category, bool>> predicate)
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .Where(predicate)
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .ToListAsync();
        }

        /// <summary>
        /// 根据条件查找单个分类
        /// </summary>
        public async Task<Category?> FindSingleAsync(Expression<Func<Category, bool>> predicate)
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .FirstOrDefaultAsync(predicate);
        }

        /// <summary>
        /// 获取分类的所有祖先
        /// </summary>
        public async Task<List<Category>> GetAncestorsAsync(long categoryId)
        {
            var ancestors = new List<Category>();
            var category = await _context.Categories.FindAsync(categoryId);
            
            while (category?.ParentId != null)
            {
                var parent = await _context.Categories.FindAsync(category.ParentId);
                if (parent != null)
                {
                    ancestors.Insert(0, parent);
                    category = parent;
                }
                else
                {
                    break;
                }
            }
            
            return ancestors;
        }

        /// <summary>
        /// 根据ID获取分类
        /// </summary>
        public async Task<Category?> GetByIdAsync(object id)
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .FirstOrDefaultAsync(c => c.Id == (long)id);
        }

        /// <summary>
        /// 根据路径获取分类
        /// </summary>
        public async Task<Category?> GetByPathAsync(string path)
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .FirstOrDefaultAsync(c => c.Slug == path);
        }

        /// <summary>
        /// 根据类型获取分类列表
        /// </summary>
        public async Task<List<Category>> GetByTypeAsync(string type)
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .Where(c => c.Type == type)
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .ToListAsync();
        }

        /// <summary>
        /// 根据父分类ID获取子分类列表
        /// </summary>
        public async Task<List<Category>> GetChildrenAsync(long parentId, bool includeDisabled = false)
        {
            var query = _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .Where(c => c.ParentId == parentId);
                
            if (!includeDisabled)
                query = query.Where(c => c.Status == 1);
                
            return await query
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .ToListAsync();
        }

        /// <summary>
        /// 获取分类的所有后代
        /// </summary>
        public async Task<List<Category>> GetDescendantsAsync(long categoryId)
        {
            var descendants = new List<Category>();
            var children = await GetChildrenAsync(categoryId, true);
            
            foreach (var child in children)
            {
                descendants.Add(child);
                var childDescendants = await GetDescendantsAsync(child.Id);
                descendants.AddRange(childDescendants);
            }
            
            return descendants;
        }

        /// <summary>
        /// 获取分页的分类列表
        /// </summary>
        public async Task<(List<Category> Items, int Total)> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<Category, bool>>? predicate = null)
        {
            var query = _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .AsQueryable();
                
            if (predicate != null)
                query = query.Where(predicate);
                
            var total = await query.CountAsync();
            
            var items = await query
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize)
                .ToListAsync();
                
            return (items, total);
        }

        /// <summary>
        /// 获取树形结构的分类列表
        /// </summary>
        public async Task<List<Category>> GetTreeAsync(string? type = null, long? parentId = null)
        {
            var query = _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .Where(c => c.Status == 1)
                .AsQueryable();
                
            if (!string.IsNullOrEmpty(type))
                query = query.Where(c => c.Type == type);
                
            if (parentId.HasValue)
                query = query.Where(c => c.ParentId == parentId.Value);
            else
                query = query.Where(c => c.ParentId == null);
                
            return await query
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .ToListAsync();
        }

        /// <summary>
        /// 保存更改
        /// </summary>
        public async Task<int> SaveChangesAsync()
        {
            return await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 获取所有分类
        /// </summary>
        async Task<List<Category>> IRepository<Category>.GetAllAsync()
        {
            return await _context.Categories
                .Include(c => c.Parent)
                .Include(c => c.Children)
                .OrderBy(c => c.SortOrder)
                .ThenBy(c => c.Name)
                .ToListAsync();
        }
    }
}
